package rbac.interceptor;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.StrutsStatics;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import rbac.entity.RbacUser;
import rbac.service.AccessControlService;
import rbac.service.UserService;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.pandawork.core.log.LogClerk;

/**
 * 访问权限控制拦截器.
 * 
 * @author Huadi
 * @author Zoufengyang
 */
public abstract class AccessControlInterceptor extends AbstractInterceptor {

    private static final long serialVersionUID = 5154643114463542734L;

    // ---=== Fields ===--- //
    private String toLoginString; // 登录 Action 返回值. 即返回哪个字符串时, 转到登录页面.

    /** 用户 service, 负责读取当前用户信息. */
    @Autowired
    @Qualifier("userService")
    protected UserService rbacUserService; // 用户 service.

    /** 访问控制 service, 负责查询某个用户是否具有访问某个资源的权限. */
    @Autowired
    @Qualifier("accessControlService")
    protected AccessControlService accessControlService;

    // ---=== Methods ===--- //
    /**
     * 拦截器验证方法.
     * 
     * @return 验证通过返回 invoke(), 不通过返回 "403", 用户未登录返回
     *         <code>toLoginString</code> 中保存的字符串.
     */
    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionContext ac = invocation.getInvocationContext();

        // 准备 当前请求中的 action 信息. 拼装 nameSpace 与 actionName 字符串.
        String nameSpace = invocation.getProxy().getNamespace();
        String actionName = "/" + ac.getName();
        if (!"/".equals(nameSpace)) {
            actionName = nameSpace + actionName;
        }

        // 获取当前登录用户信息.
        //TODO　测试跳过ｃａｓ
        HttpServletRequest request = (HttpServletRequest) ac.get(StrutsStatics.HTTP_REQUEST);
        AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
        String rbacUserName = principal.getName();
        		//TODO　测试跳过ｃａｓ
//        String rbacUserName = "admin";
        RbacUser userEntity = queryByName(rbacUserName);
        if (null == userEntity) {
            return toLoginString;
        }

		if (accessControlService.isHavePermission(userEntity, actionName)) {
		    // 登录成功，开始配置登录名
		    request.setAttribute("loginName", userEntity.getUserName());
		    request.setAttribute("realName", rbacUserName);
			return invocation.invoke();
		} else {
			LogClerk.monitorLog.error("Request refused by RBAC interceptor.");
			return "403";
		}

    }

    protected abstract RbacUser queryByName(String loginName);

    // ---=== Getters and Setters ===--- //
    /**
     * @param toLoginString the toLoginString to set
     */
    public void setToLoginString(String toLoginString) {
        this.toLoginString = toLoginString;
    }

}
